package com.star.mentor.service.impl;

import cn.hutool.core.codec.Base62;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.star.common.utils.Dates;
import com.star.mentor.contants.MentorRedis;
import com.star.mentor.dto.MentorPageDTO;
import com.star.mentor.dto.MentorSaveDTO;
import com.star.mentor.dto.MentorUpdateWxmentorDTO;
import com.star.mentor.entity.Mentor;
import com.star.mentor.entity.MentorEvaluation;
import com.star.mentor.mapper.MentorMapper;
import com.star.mentor.service.MentorEvaluationService;
import com.star.mentor.service.MentorService;
import com.star.mentor.vo.MentorPageVO;
import com.star.star.entity.Star;
import com.star.system.service.UserService;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 导师 服务实现类
 *
 * @author yangzj
 */
@Service
public class MentorServiceImpl extends ServiceImpl<MentorMapper, Mentor> implements MentorService {

    @Autowired
    private RedissonClient redisson;
    @Autowired
    private UserService userService;
    @Autowired
    private MentorEvaluationService mentorEvaluationService;

    @Override
    public String getInvitationCode() {
        String code = IdUtil.nanoId(8);
        // 存一下
        redisson.getBucket(MentorRedis.INVITATION_CODE + code).set(1, 5, TimeUnit.MINUTES);
        return code;
    }

    @Override
    public void save(MentorSaveDTO dto) {
        String invitationCode = dto.getInvitationCode();
        Object o = redisson.getBucket(MentorRedis.INVITATION_CODE + invitationCode).get();
        Assert.notNull(o, "邀请码失效，请重新生成");
        Assert.isFalse(this.lambdaQuery().eq(Mentor::getInvitationCode, invitationCode).exists(), "邀请重复，请重新生成");
        this.save(new Mentor().setInvitationCode(dto.getInvitationCode())
                .setInvitationExpire(dto.getInvitationExpire())
                .setInvitationTime(LocalDateTime.now()).setEnabled(true));
    }

    @Override
    public void updateEnabled(Long id, boolean enabled) {
        this.updateById(new Mentor().setId(id).setEnabled(enabled));
    }

    @Override
    public void updateInvitationExpire(Long id, Integer invitationExpire) {
        this.updateById(new Mentor().setId(id).setInvitationExpire(invitationExpire)
                .setInvitationTime(LocalDateTime.now()));
    }

    @Override
    public void deleteById(Long id) {
        Mentor mentor = Assert.notNull(this.getById(id), "导师（邀请码）不存在");
        boolean validate = this.validate(mentor.getInvitationTime(), mentor.getInvitationExpire());
        Assert.isFalse(validate, "邀请码还未过期，不能删除");
        Assert.isFalse(mentor.getUserId() != null, "邀请码已绑定导师，不能删除");
        this.removeById(id);
    }

    @Override
    public IPage<MentorPageVO> page(MentorPageDTO dto) {
        IPage<MentorPageVO> page = baseMapper.page(dto);
        page.getRecords().forEach(c -> this.validate(c.getInvitationTime(), c.getInvitationExpire()));
        return page;
    }


    @Override
    public Mentor getByUserId(Long userId) {
        return this.getOne(Wrappers.<Mentor>lambdaQuery().eq(Mentor::getUserId, userId));
    }

    @Override
    public Long validateWxmentor(String invitationCode) {
        Mentor mentor = Assert.notNull(this.getOne(Wrappers.<Mentor>lambdaQuery().eq(Mentor::getInvitationCode, invitationCode))
                , "邀请码不存在，请核对");
        Assert.isTrue(this.validate(mentor.getInvitationTime(), mentor.getInvitationExpire()), "邀请码已过期");
        return mentor.getId();
    }

    /**
     * 验证邀请码是否还有效
     *
     * @param invitationTime   邀请时间
     * @param invitationExpire 邀请过期
     * @return boolean
     */
    private boolean validate(LocalDateTime invitationTime, Integer invitationExpire) {
        DateTime offsetMinute = DateUtil.offsetMinute(Dates.toDate(invitationTime), invitationExpire);
        return offsetMinute.isAfterOrEquals(new Date());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateWxmentor(MentorUpdateWxmentorDTO dto, Long userId) {
        Assert.isTrue(this.lambdaQuery().eq(Mentor::getId, dto.getId()).exists(), "导师不存在");
        this.updateById(new Mentor().setId(dto.getId()).setUserId(userId)
                .setRealName(dto.getRealName())
                .setStyles(dto.getStyles()));
        // 更新用户信息
        userService.updateMentorInfo(dto);
        // 再分配还没评估的学员
        mentorEvaluationService.allocationNotEvaluation();
    }

    @Override
    public List<Mentor> listEnabled() {
        return this.list(Wrappers.<Mentor>lambdaQuery().isNotNull(Mentor::getUserId).eq(Mentor::getEnabled, true));
    }

}
